#!/usr/bin/env python

import os
import logging
import ConfigParser

import gobject
import dbus
import dbus.mainloop.glib

try:
    import pynotify
    module_pynotify = True
except ImportError:
    module_pynotify = False

# System-wide log file
LOG_FILE = '/tmp/system-event-manager.log'

devices_monitored = []


def handler_nm_properties_changed(props):
    if not props.has_key('ActiveConnections'):
        return

    for device_path in props['ActiveConnections']:
        if device_path in devices_monitored:
            logging.debug("Device " + device_path + " is already monitored. Skipping.")
            continue
        device = get_nm_object(device_path)
        device_props = get_properties(device, "org.freedesktop.NetworkManager.Connection.Active")
        if device_props['Default']:
            continue
        ap_path = device_props['SpecificObject']

        # This section filters WiFi access points
        if ap_path.startswith('/org/freedesktop/NetworkManager/AccessPoint/'):
            ap = get_nm_object(ap_path)
            ssid = get_property(ap, "org.freedesktop.NetworkManager.AccessPoint", "Ssid")
            ssid = ''.join([chr(c) for c in ssid])
            logging.debug("Device " + device_path + " ssid:" + ssid + " is connected to be monitored.")
            devices_monitored.append(device_path)
            device.connect_to_signal("PropertiesChanged",
                                     handler_nm_device_properties_changed(ssid),
                                     dbus_interface="org.freedesktop.NetworkManager.Connection.Active")


def handler_nm_device_properties_changed(ssid):
    def handler(props):
        if not props.has_key('State') or props['State'] != 2:
            return

        section = dict(config.items("WiFi Up"))
        execute_action = section['execute']
        logging.debug("Running action: " + execute_action)
        os.system(execute_action)

        caption = "Successfully executed script " + execute_action + " on " + ssid

        if module_pynotify:
            try:
                notification = pynotify.Notification("System events manager", caption, "network-wireless")
                notification.set_urgency(pynotify.URGENCY_NORMAL)
                notification.set_timeout(10)
                notification.show()
            except:
                pass
        logging.info(caption)
    return handler


def get_nm_object(path):
    return bus.get_object("org.freedesktop.NetworkManager", path)


def get_property(obj, interface, property):
    return obj.Get(interface, property, dbus_interface="org.freedesktop.DBus.Properties")


def get_properties(obj, interface):
    return obj.GetAll(interface, dbus_interface="org.freedesktop.DBus.Properties")


if __name__ == '__main__':
    # Read config
    config = ConfigParser.RawConfigParser()
    config.read([
        '/etc/system-event-manager.conf',           # system wide
        'system-event-manager.rc'])                 # and developing one. Shouldn't be used in production

    # Setup logging
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                        datefmt='%m-%d %H:%M',
                        filename=LOG_FILE,
                        filemode='a')

    consoleHandler = logging.StreamHandler()
    consoleHandler.setLevel(logging.DEBUG)
    consoleHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s %(message)s'))
    logging.getLogger('').addHandler(consoleHandler)
    logging.info("system-event-manager started...")

    # Init pynotify
    if module_pynotify:
        if not pynotify.init("system-event-manager"):
            logging.error("Can't initialize pynotify module")
            module_pynotify = False

    # Initialize dbus reactor
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()
    nm = get_nm_object("/org/freedesktop/NetworkManager")
    nm.connect_to_signal("PropertiesChanged",
                         handler_nm_properties_changed,
                         dbus_interface="org.freedesktop.NetworkManager")

    loop = gobject.MainLoop()
    loop.run()
